<template>
  <!-- start 工单进度 -->
  <div class="task-info-record">

    <!-- start 时间轴 -->
    <div class="task-timeline" :style="inputState?'padding-bottom:210px;':'padding-bottom:70px;'" ref="timeline">
      <base-timeline
        :data="recordPage.list"
        :record-render="renderRecord"
        :loading="recordLoading"
        :loadmore="recordPage.hasNextPage"
        @load="loadmore"
      />
      <!-- <base-timeline-V2 :list-data="recordPage" mode="task" >
      </base-timeline-V2> -->
    </div>
    <!-- end 时间轴 -->
    <!-- start 添加备注 -->
    <div class="customer-quick-comment" :style="commentStyle" v-if="editComment && !isArchive">
      <biz-comment ref="comment" @inputStateChange='inputStateChange' @saveNoteToCustomer="saveNoteToCustomer" @changeHideTips="changeHideTips" :placeholder="$t('customer.detail.customerInfoRecord.remarkPlaceholder')" :template-list="remarkTemplateList" :show-customer-action="true" @submit="createRemark" :disabled="commentPending" autofocus user-search-url="/message/user/lists" :search-params="{seeAllOrg:true}" :hide-tips="hideTips" 
      :always-check-to-customer="alwaysCheckToCustomer"></biz-comment>
      <!-- <base-comment ref="comment" @inputStateChange='inputStateChange' placeholder="请输入备注内容" :template-list="remarkTemplateList" :show-customer-action="true" @submit="createRemark" :disabled="commentPending" autofocus/> -->
    </div>
    <!-- end 添加备注 -->
  </div>
  <!-- end 工单进度 -->
</template>

<script>
/* api */
import * as TaskApi from '@src/api/TaskApi.ts';
/* utils */
import { isOpenData } from '@src/util/platform';
import _, { debounce } from 'lodash';
import { trimAll, formatDate, cutAtTextContent } from 'pub-bbx-utils';
import Page from '@model/Page';
import { openTabForEventView } from '@src/util/business/openTab';
import { t } from '@src/locales'
import { translateAction } from '@src/util/record'
import { getUserGuideStorageBase, setUserGuideStorageBase } from '@src/util/guideStorage';
import {
  storageGet,
  storageSet
} from '@src/util/storageV2';
/* enum */
import { TaskEventNameMappingEnum } from '@model/enum/EventNameMappingEnum.ts';
import { ApproveActionLabelEnum } from '@model/enum/LabelEnum.ts'

import { isBasicEditionHideEvent } from '@shb-lib/version';
import { useTenantId } from '@hooks/useRootWindow.ts';
/* mixin */
import { ConnectorModuleConnectorRecordMixin, ConnectorModuleTriggerRecordMixin } from '@src/modules/connector'
import addressMixin from '@src/mixins/addressMixin';

const hideNoteStorageKey = 'taskremark_notetocustomer_tips_hide'
const checkNoteToCustomerStorageKey = 'taskremark_notetocustomer_ischeck'
function createAttachmentDom(h, attachments, type){
  return attachments && attachments.length > 0
    ? <div class={ `base-timeline-attachment base-file__preview ${type}` }>
      {attachments.map(item => <base-file-item Source={attachments} file={item} key={item.id} readonly size="small"/>)}
    </div>
    : ''
}
function createLinkDom(h, s){
  const reg = /((((https?|ftp?):(?:\/\/)?)(?:[-;:&=\+\$]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\?\+=&;:%!\/@.\w_]*)#?(?:[-\+=&;%!\?\/@.\w_]*))?)/g;
  const str = s.replace(reg, str=>`@#@${str}@#@`);
  const arr = str.split('@#@');
  return <p class="pre-line secondary-info">{arr.map(item=>{
    if(item.indexOf('http') === 0){
      return <a href={item} target='_blank'>{item}</a>
    }
    return <biz-comment-html html={item}></biz-comment-html>

  })}</p>
}

export default {
  name: 'task-info-record',
  inject: ['initData'],
  mixins: [ConnectorModuleConnectorRecordMixin, ConnectorModuleTriggerRecordMixin,addressMixin],
  props: {
    showTemplate: {
      type: Boolean,
      default: true
    },
    shareData: {
      type: Object,
      default: () => ({})
    },
    taskLayout: {
      type: Number,
      default: 2
    }
  },
  data() {
    return {
      commentPending: false,
      params: {
        taskId: this.taskId,
        pageNum: 1,
        pageSize: 15,
      },
      recordLoading: false,
      recordPage: new Page(),
      inputState:false,
      alwaysCheckToCustomer:false,
      hideTips:false
    }
  },
  computed: {
    commentStyle(){
      if (this.taskLayout === 1) {
        return 'width:calc(100% - 33px); bottom:0;'
      }
      if(this.shareData.collapseDirection === 'left'){
        return 'width:calc(100% - 175px); bottom:0;'
      }else if(this.shareData.collapseDirection === ''){
        return 'width:calc(50% - 33px);bottom:0;'
      }return 'width:70%;max-width:calc(100% - 445px);bottom:0;'
    },
    address() {
      return this.shareData?.address || '';
    },
    auth() {
      return this.shareData?.auth || {};
    },
    isArchive(){
      return this.shareData?.isArchive || false
    },
    // 权限
    authorities(){
      let user = this.loginUser || {};
      return user.authorities || {};
    },
    allTaskEdit() {
      return this.authorities['TASK_EDIT'] === 3;
    },
    /** 是否允许操作 */
    allowOperate(){
      return this.task?.isDelete === 0;
    },
    /** 查看单权限 */
    allowTaskView() {
      return this.initData?.canViewTask === true;
    },
    /** 事件转工单后 查看事件权限 */
    canViewRelationEvent() {
      return this.initData?.canViewRelationEvent;
    },
    customer() {
      return this.task?.customer || {};
    },
    /** 添加备注权限 */
    editComment(){
      return this.allowTaskView && this.allowOperate;
    },
    loginUser(){
      return this.initData?.loginUser || {};
    },
    linkman() {
      return this.shareData?.linkman || {};
    },
    task() {
      return this.shareData?.task || {};
    },
    taskId() {
      return this.task?.id;
    },
    taskNo() {
      return this.task?.taskNo;
    },
    remarkTemplateList() {
      return this.showTemplate ? this.initData.remarkList : [];
    },
    // 开启审批签名
    enableTaskApproveSign() {
      return this.initData?.taskApproveSignConfig?.open;
    },
    // 基础版功能隐藏事件
    isBasicEditionHideEvent() {
      return isBasicEditionHideEvent()
    },
  },
  watch: {
    taskId: {
      handler(newValue) {
        if(newValue) {
          this.initializeRecord()
        }
      }
    }
  },
  mounted() {
    this.initializeRecord();
    this.getUserSetForNoteCustomerStorage();
    this.$eventBus.$on(TaskEventNameMappingEnum.UpdateRecord, this.searchRecord);
  },
  beforeDestroy() {
    this.$eventBus.$off(TaskEventNameMappingEnum.UpdateRecord, this.searchRecord);
  },
  methods: {
    // 获取action的多语言label
    getActionLabel(key) {
      return ApproveActionLabelEnum[key] || key
    },
    // 普通字符串转成数组
    renderStringChangeArray(string){
      let arrayStr = string ?? ''
      let arr = []
      if(arrayStr.length){
        arrayStr = arrayStr.substring(1, arrayStr.length - 1).split(',')
        arrayStr.forEach(item => {
          item = item.substring(1, item.length - 1)
          arr.push(item)
        })
      }
      return arr
    },
    inputStateChange(val){
      this.inputState = val;
    },
    /**
     * 同时满足以下条件允许删除该记录
     * 1. 该记录没有被删除
     * 2. 工单编辑权限（CUSTOMER_EDIT）值为3 或者 是创建人
     * 3. 该工单没有被删除
     */
    allowDeleteRecord(item){
      let isDelete = item.content.isDelete == 'true'
      let user = this.loginUser
      let isCreator = item.userId == user.userId

      return !isDelete && (this.allTaskEdit || isCreator) && this.allowOperate;
    },
    /**
     * @description 创建备注
    */
    async createRemark(form) {
      try{
        this.commentPending = true;
        let task = this.task
        let tenantId = useTenantId().value;
        let url = ''
        if(form.receivers){
          url = `tenantId=${tenantId}&bizId=${task.id}&sendUserName=${this.initData.loginUser.displayName}&receivers=${form.receivers}&templateId=${task.templateId}&templateName=${task.templateName}&bizNo=${task.taskNo}`
          url += `&content=${cutAtTextContent(form.originalContent)}`
        }

        let params = {
          taskId: this.taskId,
          attachment: form.attachments,
          showInOwn: form.showInOwn,
          toCustomer: form.toCustomer,
          cusNotice: form.cusNotice,
          content: form.content,
          cusRemarksNotice: form.cusRemarksNotice
        }

        let result = await TaskApi.taskRecordCreate(url, params);

        if (result.success) {
          // 清除备注信息
          this.$refs.comment.reset();
          // 初始化备注
          await this.initializeRecord();
          // 滚动到顶部
          this.$nextTick(() => {
            this.$refs.timeline.scrollTop = 0;
          })
        } else {
          this.$platform.alert(result.message)
        }

      } catch(err){
        console.warn(err)
      } finally {
        this.commentPending = false;
      }
    },
    /**
     * @description 删除备注
    */
    async deleteRemark(record) {
      try {
        if (!await this.$platform.confirm(this.$t('task.tip.deleteRemarkTip'))) return;
        const result = await TaskApi.taskRecordDelete({ id: record.id });

        if (result.success) {
          this.initializeRecord();
        } else {
          this.$platform.alert(result.message)
        }

      } catch (e) {
        console.warn('task deleteRemark -> error', e);
      }
    },
    /**
     * @description 抓取信息动态
    */
    fetchRecord(params){
      params.taskId = this.taskId;
      params.userId = this.loginUser.userId;
      params.hasViewBalanceRecord = 1;
      params.hasViewReviewRecord = 1;

      const api = this.isArchive ? TaskApi.taskArchiveRecordList : TaskApi.taskRecordList;
      return api(params).then(data => {
        let { list = [] } = data?.result;
        list.forEach(record => {
          try {
            record.attachments = JSON.parse(record.attachments);
            record.content = JSON.parse(record.content);
          } catch (error) {
            record.attachments = [];
            record.content = { updateContent: record.content };
            console.warn('searchRecord recordPage.list.forEach -> error', error)
          }
        })

        return data;
      })
    },
    /**
     * @description 初始化信息动态
    */
    async initializeRecord() {
      this.params.pageNum = 1;
      this.searchRecord();
    },
    /**
     * @description 加载下一页
    */
    async loadmore() {
      try {
        this.params.pageNum++;
        this.recordLoading = true;

        let data = await this.fetchRecord(this.params);

        this.recordLoading = false
        this.recordPage.merge(data.result)

      } catch (error) {
        console.warn('loadmore -> error', error)
      }
    },

    recordPageListConvertHandler(list = []) {
      list.forEach(record => {
        try {
          record.attachments = JSON.parse(record.attachments);
        } catch (error) {
          console.warn('searchRecord  recordPage.list.forEach -> error', error)
        }
      })
    },
    /**
     * @description 渲染地址dom
     * @param {Object} record 记录数据
     * @param {Boolean} isFinished 是否是完成状态 特殊处理
    */
    renderAddressRecordDom(record = {}, isFinished = false) {
      let address = trimAll(record.address || '');
      let { latitude, longitude } = record;
      let isShowAddress = address && latitude && longitude;
      let openMapFunc = isFinished ? this.openMapForFinished : this.openMap
      let icon = isShowAddress ? <i class="iconfont icon-address"></i> : '';
      let addressDom = <span onClick={e => {openMapFunc(record)}}>{icon}{address}</span>;
      return { address, icon, isShowAddress, addressDom }
    },
    /* 渲染指派转派 */
    renderAllotDom(record = {}) {
      let { action, userName, content, taskNo, executorName, staffId, executorStaffId, userId, executorId } = record;
      let { customExceptionReason, customReason } = content
      let allotReason = customExceptionReason || customReason
      let allotReasonDom = [
        allotReason && <div>{`${t('task.detail.components.transferDesc')}：${allotReason}`}</div>,
        content.updateContent && <div>{t('task.detail.components.detailDesc')}：<biz-comment-html html={content.updateContent}></biz-comment-html></div>
      ]
      const overRecordsArr = this.renderStringChangeArray(content.overRecords);
      return (
        <div class="task-record-allot">
          <i18n path={`common.record.task['${action}']`} tag="h5">
            <span place="operator" >{this.renderUserName(userName, staffId, userId)}</span>
            <span place="taskNo">{taskNo}</span>
            <span place="recipient">
              {
                content.serviceProviderName && <span>{`${t('common.base.serviceProvider')} #${content.serviceProviderName}-`}</span>
              }
              {this.renderUserName(executorName, executorStaffId, executorId)}
            </span>
            <span place="other">{overRecordsArr.length > 0 && <div>{overRecordsArr[0]}</div>}</span>
          </i18n>

          {(content && Object.keys(content).length > 0) && (
            <div>
              {content.synergy && <div>{t('common.label.synergiesUser')}：{this.renderSynergyName(content.synergy, content.synergyStaffId)}</div>}
              {content.updateType == 'tRecord' && (
                (action == '转派') ? allotReasonDom : <div><biz-comment-html html={content.updateContent}></biz-comment-html></div>
              )}
            </div>
          )}
        </div>
      )
    },
    /* 自定义异常 */
    abnormalRender(record = {}) {
      let { content } = record;
      const actionDes = translateAction(content.action)
      return (<div>{t('common.record.task.abnormal', {action:actionDes})}</div>)
    },

    /**
     * 附件记录
     */
    renderAttachment(record = {}){
      let { userName, taskNo } = record;
      return (<i18n path="common.record.task.attachment" tag="div"><strong place="operator">{userName}</strong><span place="taskNo">{taskNo}</span></i18n>)
    },

    /**
     * 编辑结算
     */
    renderEditSettlement(record = {}){
      let { userName, taskNo,staffId,action } = record;
      return (<i18n path="common.record.task.editSettlement" tag="div"><span place="operator">{this.renderUserName(userName, staffId)}</span><span place="taskNo">{taskNo}</span></i18n>)
    },

    /* 渲染添加备注 */
    renderActionRemarkDom(h, record = {}) {
      let { userName, showInOwn, toCustomer, cusNotice, content, attachments, cusRemarksNotice, staffId, userId } = record;
      return [
        <h5 class="main-info">
          <i18n path="common.record.task.somebodyAddRemark" tag="span">
            <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          </i18n>
          {!!showInOwn && (
            <span class="private"> <i class="iconfont icon-account1"></i> {t('task.record.onlyVisibleToYourself')} </span>
          )}。
          {!!toCustomer && <span class=""> ({t('task.record.visibleToCustomer')}) </span> }
          {(!!cusNotice && cusRemarksNotice !== 1) && <span class=""> ({t('task.record.notifyCustomerBySms')}) </span> }
          {!!cusRemarksNotice && <span class=""> ({t('task.record.notifyCustomerBySmsAndRemark')}）) </span> }
          {
            this.allowDeleteRecord(record)
            && (
              <button type='button' class="btn-text base-timeline-delete" onClick={e => this.deleteRemark(record)}>
                <i class="iconfont icon-shanchu"></i>{t('common.base.delete')}
              </button>
            )
          }
        </h5>,
        content.isDelete == 'true'
          ? <i18n path="common.record.task.somebodyDeleteRemark" tag="p" class="text-danger">
              <span place="operator">{this.renderUserName(content.deleteUserName, content.deleteUserStaffId)}</span>
              <span place="time">{ formatDate(content.deleteTime) }</span>
            </i18n>
          // <p class="text-danger">{this.renderUserName(content.deleteUserName, content.deleteUserStaffId)}于{content.deleteTime}删除了该备注。</p>
          : [createLinkDom(h, content.updateContent), createAttachmentDom(h, attachments)]
      ]
    },
    /* 渲染api新建 */
    renderApiCreateDom(record = {}) {
      let { userName, content, taskNo, staffId, userId } = record;
      return [
        <i18n path="common.record.task.taskCreateByApi" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="apiName">{content.clientName}</span>
          <span place="taskNo">{taskNo}</span>
        </i18n>
      ]
    },
    /* 渲染工单自动分配dom */
    renderTaskAutoAllotDom(record = {}) {
      let { executorName = '', content, taskNo, executorStaffId, executorId } = record;
      return <i18n path="common.record.task.taskAutoAllot" tag="div">
        <span place="taskNo">{taskNo}</span>
        <span place="ruleName">{ content.ruleName }</span>
        <span place="operator">{this.renderUserName(executorName, executorStaffId, executorId)}</span>
      </i18n>
    },
    /* 渲染工单自动分配失败dom */
    renderTaskAutoAllotFailDom(record = {}) {
      let { content, taskNo } = record;
      return <div class="task-record-fail">{t('common.record.task.taskAutoAllotFail', {taskNo, data1:content.fail})}</div>
    },
    /* 渲染工单自动派单dom */
    renderTaskAutoDispatchDom(record = {}) {
      let { executorName = '', content, taskNo, executorStaffId, executorId } = record;
      return <i18n path="common.record.task.taskAutoDispatch">
        <span place="taskNo">{ taskNo }</span>
        <span place="ruleName">{ content.ruleName }</span>
        <span place="operator">{this.renderUserName(executorName, executorStaffId, executorId)}</span>
      </i18n>
    },
    /* 渲染基础的工单动作 */
    renderBaseTaskAction({ action, userName, taskNo, staffId, content, userId }) {
      const overRecordsArr = this.renderStringChangeArray(content.overRecords);
      return <i18n path={`common.record.task['${action}']`} tag="h5">
        <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
        <span place="taskNo">{taskNo}</span>
        <div place="other" style={{ display: overRecordsArr.length ? 'block' : 'none' }} >{overRecordsArr[0]}</div>
      </i18n>
      // return <h5> {this.renderUserName(userName, staffId, userId)} {action}了工单 #{taskNo}。<div style={{ display: overRecordsArr.length ? 'block' : 'none' }} >{overRecordsArr[0]}</div></h5>
    },
    /* 渲染留言 */
    renderLeaveMessageDom(h, record = {}) {
      let { userName, content, attachments, staffId, userId } = record;
      let customerName = userName ? userName : content?.customerName
      return [
        <i18n path="common.record.task.somebodyAddRemark2" tag="h5" class="main-info">
          <span place="operator">{this.renderUserName(customerName, staffId, userId)}</span>
        </i18n>,
        // <h5 class="main-info">
        //   {this.renderUserName(customerName, staffId, userId)} 添加了留言
        // </h5>,
        content.isDelete == 'true'
          ? <i18n path="common.record.task.somebodyDeleteRemark2" tag="p" class="text-danger">
              <span place="operator">{this.renderUserName(content.deleteUserName, content.deleteUserStaffId)}</span>
              <span place="time">{ formatDate(content.deleteTime) }</span>
            </i18n>
          // <p class="text-danger">{ this.renderUserName(content.deleteUserName, content.deleteUserStaffId) }于{ content.deleteTime }删除了该留言。</p>
          : [<p class="pre-line secondary-info">{ content.updateContent || content.content }</p>, createAttachmentDom(h, attachments)]
      ]
    },
    /* 渲染电话日志 */
    renderPhoneLogDom(record = {}) {
      let { userName, content, staffId, userId } = record;
      return <i18n path="common.record.task.phoneLog" tag="h5">
        <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
        <strong place="targetName">{ content.targetName }</strong>
      </i18n>
    },
    /* 渲染编辑回执dom */
    renderReceiptEditDom({ userName, taskNo, staffId, userId }) {
      let addressData = this.renderAddressRecordDom(...arguments);
      return [
        <i18n path="common.record.task.receiptEdit" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">#{taskNo}</span>
        </i18n>,
        // <h5> {this.renderUserName(userName, staffId, userId)} 编辑了工单回执 #{taskNo}。</h5>,
        addressData.isShowAddress ? <div class="form-view-row-content-address">{ addressData.addressDom }</div> : ''
      ]
    },
    /* 渲染发布到工单池dom */
    renderReleaseTaksPoolDom(record = {}) {
      let { action, userName, content, taskNo, staffId, userId } = record;
      let synergyDom = content.synergy ? <div>{t('common.label.synergiesUser')} {this.renderSynergyName(content.synergy, content.synergyStaffId)}</div> : '';
      let contentDom = content.toTaskPool === '1'
        ? <p class="pre-line secondary-info">{t('task.detail.components.transferDesc')}：<biz-comment-html html={content.updateContent}></biz-comment-html></p>
        : <p class="pre-line secondary-info"><biz-comment-html html={content.updateContent}></biz-comment-html></p>;

      return [
        <i18n path="common.record.task.releaseTaksPool" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{ taskNo }</span>
        </i18n>,
        // <h5>{this.renderUserName(userName, staffId, userId)} 把工单 #{ taskNo } { action } 到工单池。</h5>,
        <div>
          { synergyDom }
          { content.updateType == 'tRecord' ? contentDom : '' }
        </div>
      ]
    },
    /* 渲染开始和完成 */
    renderStartOrFinishDom(record = {}) {
      let { content, address, action } = record;
      let isFinished = action == '完成'
      let addressData = this.renderAddressRecordDom(record, isFinished);
      let isPositionException = content.isPositionException == 'true';
      let className = isPositionException ? 'task-position-exception' : '';
      let startOrFinshRecord = [
        // 基础工单操作日志
        <div> { this.renderBaseTaskAction(record) } </div>,
        // 地址操作
        <div>
          { address === 'PC端' ? <span>{t('task.record.operateFromPcEnd')}</span> : <span class="form-view-row-content-address">{ addressData.addressDom }</span> }
        </div>,
        // 是否地理位置异常
        <div>
          { isPositionException && <span>{t('task.detail.components.distanceToCustomer')}：{ content.distance ? `${content.distance} km` : t('task.record.positionException') }</span> }
        </div>
      ];

      return (
        <div class={className}>
          { startOrFinshRecord }
        </div>
      )
    },
    /* 渲染出发 */
    renderSetOutDom(record = {}) {
      let { action, userName, taskNo, staffId, content, userId, address } = record;
      let addressData = this.renderAddressRecordDom(record);
      return (
        <div>
          <div>
            <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
            {this.$t('task.record.setOut')}
          </div>
          <div>
            { address === 'PC端' ? <span>{t('task.record.operateFromPcEnd')}</span> : <span class="form-view-row-content-address">{ addressData.addressDom }</span> }
          </div>
        </div>
      )
    },
    /* 渲染计划任务新建工单 */
    renderPlanTaskCreateDom(record = {}) {
      let { content, taskNo } = record;
      return <h5>{t('common.record.task.taskCreateByPlanTask', {planName:content.planName, taskNo})}</h5>
    },
    /* 渲染工单接受dom */
    renderTaskAcceptDom(record = {}) {
      let { content, userName, action, taskNo, staffId, userId } = record;
      let fromTaskPool = content.fromTaskPool == '1';
      let taskPoolAcceptDom = <i18n path="common.record.task.taskAcceptFromTaskPool" tag="h5"><span place="operator">{this.renderUserName(userName, staffId, userId)}</span><span place="taskNo">#{taskNo}</span></i18n>
      // <h5> {this.renderUserName(userName, staffId, userId)} 从工单池 {action}了工单 #{taskNo}。</h5>

      return fromTaskPool ? taskPoolAcceptDom : this.renderBaseTaskAction(record)
    },
    /* 渲染工单审批dom */
    renderTaskApproveDom(record = {}) {
      let { content, taskNo, address, attachments, userName, longitude, latitude, staffId, userId } = record;
      let { state, level } = content;
      // 工单审批状态
      let taskState = {
        unApproved: state == 'unapproved',
        success: state == 'success',
        fail: state == 'fail',
        offed: state == 'offed',
      }
      // 工单审批等级
      let levelName

      if (content?.vipApprove) {
        levelName = content.approveNode || ''
      } else {
        levelName = level >= 1 ? `${[t('common.base.level0'), t('common.base.level1'),t('common.base.level2'),t('common.base.level3'),t('common.base.level4'),t('common.base.level5'),t('common.base.level6'),t('common.base.level7'),t('common.base.level8'), t('common.base.level9')][level] }` : '';
      }

      // 是否显示地址
      let isShowAddress = address && address != 'PC端';
      // 地址数据
      let addressData = this.renderAddressRecordDom(record);
      // 地址dom
      let addressDom = isShowAddress
        ? longitude && latitude
          ? <div class="form-view-row-content-address">{ addressData.addressDom}</div>
          : <div>{ address }</div>
        : '';
      // 未审批dom
      let unApprovedDom = [
        <i18n tag="div" path={ address == 'PC端' ? 'common.record.task.taskApproveByPc' : 'common.record.task.taskApprove' }>
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{taskNo}</span>
          <span place="action">{content.action}</span>
        </i18n>,
        content.remark && <div>{t('common.base.remark')}：<biz-comment-html html={content.remark}></biz-comment-html></div>,
        content.apprNames && <div>{content.apprNames_2 ? t('common.base.approveUserLevel1') : t('common.base.approveUser')}：{ this.renderSynergyName(content.apprNames, content.apprStaffIds) }</div>,
        content.apprNames_2 && <div>{t('common.base.approveUserLevel2')}：{ this.renderSynergyName(content.apprNames_2, content.apprStaffIds_2) }</div>,
        addressDom
      ];
      // 是否展示审批签名
      const sign = content?.sign ? [content.sign] : [];
      const addApproveSignatures = <div class="form-approve-signatures">
        <span>{t('common.base.approveSign')}:</span>
        <el-image style="width: 100px; height: 100px"
          src={content?.sign}
          previewSrcList={sign}
        />
      </div>
      // 审批成功dom
      let isAutoApprove = userName == '自动审批';
      let autoApproveDom = <h5>{t('common.record.task.taskAutoApprove', {taskNo, action:content.action, approveUser:t('common.base.approveUserByLevel', {data1:levelName})})}</h5>;
      let notAutoApproveDom = [
        <i18n path="common.record.task.taskPaasApproveBysomebody" tag="div">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{taskNo}</span>
          <span place="action">{ content.action }</span>
          <span place="approve">{t('common.base.approveByLevel',{data1:levelName})}</span>
        </i18n>,
        content.remark && <div>{t('common.base.remark')}：<biz-comment-html html={ content.remark }></biz-comment-html></div>, createAttachmentDom(h, attachments),
        content.sign && addApproveSignatures
      ]
      let successDom = isAutoApprove ? autoApproveDom : notAutoApproveDom;
      // 审批失败dom
      let failDom = [
        <i18n path="common.record.task.taskRefuseApproveBysomebody" tag="div">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{taskNo}</span>
          <span place="action">{ content.action }</span>
          <span place="approve">{t('common.base.approveByLevel',{data1:levelName})}</span>
        </i18n>,
        content.remark && <div>{t('common.base.remark')}：<biz-comment-html html={ content.remark }></biz-comment-html></div>, createAttachmentDom(h, attachments),
        content.sign && addApproveSignatures
      ];
      // 审批撤回dom
      let offedDom = [
        <i18n path="common.record.task.taskWithdrawApproveBysomebody" tag="div">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{taskNo}</span>
          <span place="action">{ content.action }</span>
          <span place="approve">{t('common.base.approveByLevel',{data1:levelName})}</span>
        </i18n>
      ];

      return [
        <div>
          { taskState.unApproved ? unApprovedDom : '' }
          { taskState.success ? successDom : '' }
          { taskState.fail ? failDom : '' }
          { taskState.offed ? offedDom : '' }
        </div>
      ]

    },
    /* 渲染工单修改结算dom */
    renderTaskBalanceDom(record = {}) {
      let { content, taskNo, userName, staffId, userId } = record;
      let balanceArr = [];

      for (let name in content){
        let value = content[name];
        if(value){
          let arr = value.split('[ + + ]');
          let data = { name, oldValue: arr[0], newValue: arr[1] }

          balanceArr.push(data);
        }
      }

      return [
        <i18n path="common.record.task.taskBalance" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{taskNo}</span>
        </i18n>,
        balanceArr.map(review => {
          return <i18n path="common.record.task.taskReviewModifield" tag="div">
            <strong place="data1">{ review.name }</strong>
            <strong place="value1">{ review.oldValue }</strong>
            <strong place="value2">{ review.newValue }</strong>
          </i18n>
        })
      ]
    },
    /* 渲染工单附加组件卡片 */
    renderTaskCardDom(record = {}) {
      let { userName, content, staffId, userId } = record;
      return <i18n path={`common.record.task.taskCard['${content.action}']`} tag="div">
        <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
        <span place="cardName">{ content.cardName }</span>
      </i18n>
    },
    /* 渲染工单创建dom */
    renderTaskCreatetDom(record = {}) {
      let { content = {} } = record
      let { eventId, eventNo } = content
      let isEventToTask = Boolean(eventId)

      return [
        this.renderBaseTaskAction(record),
        isEventToTask ? this.isBasicEditionHideEvent || !this.canViewRelationEvent ? <span>{t('common.record.task.taskCreateByEvent', {eventNo:`#${eventNo}`})}</span> : <span onClick={event => openTabForEventView(eventId)}><i18n path="common.record.task.taskCreateByEvent" tag="span"><span place="eventNo" class="link-text"># {eventNo} </span></i18n></span> : ''
      ]
    },
    /* 渲染工单修改dom */
    renderTaskEditDom(record = {}) {
      let { content } = record;
      return [
        this.renderBaseTaskAction(record),
        content.updateFields && <div>{t('task.record.modifyField')}：{ content.updateFields } </div>,
        content.planTime && <div>{t('common.task.flow.planTime')}：{ formatDate(content.planTime) } </div>
      ]
    },
    /* 渲染工单暂停dom */
    renderTaskPausedDom(record = {}) {
      let { action, content, taskNo, userName, staffId, userId } = record;
      let customExceptionReasonDom = content.customExceptionReason && <div>{t('task.pauseReason')}：{ content.customExceptionReason }</div>
      let reasonDom = content.reason && <div>{t('task.detailReason')}：<biz-comment-html html={ content.reason }></biz-comment-html></div>
      return (
        <div class="task-record-fail">
          <i18n path="common.record.task['暂停']"  tag="div">
            <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
            <span place="taskNo">{taskNo}</span>
          </i18n>
          { customExceptionReasonDom }
          { reasonDom }
        </div>
      )
    },
    /* 渲染回访短信dom */
    renderTaskCodeReviewDom(record = {}){
      let { action, taskNo, userName, staffId, userId } = record;
      return (
        <i18n path="common.record.task.taskCodeReview" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">#{taskNo}</span>
        </i18n>
      )
    },
    /* 渲染工单支付dom */
    renderTaskPaymentDom(record = {}) {
      let { userName, taskNo, staffId, userId } = record;
      return <i18n path="common.record.task.taskPayment" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{taskNo}</span>
        </i18n>
    },
    /* 渲染工单回访dom */
    renderTaskReviewDom(record = {}) {
      let { content } = record;
      let degree = '';
      let tag = '';
      let star = [];
      let reviewArr = [];
      record.action = content.temp ? '暂存' : record.action === '回访' ? '完成回访' : record.action;
      for (let name in content){
        let value = content[name] || '';
        let arr = value.split('[ + + ]');
        let data = { name, oldValue: arr[0], newValue: arr[1] }

        if (name == '满意度') {
          degree = _.cloneDeep(data);
        } else if (name == '服务标签') {
          tag = _.cloneDeep(data);
        } else {
          star.push(data);
        }
      }

      if (degree) reviewArr.push(degree)
      if (star) reviewArr = reviewArr.concat(star)
      if (tag) reviewArr.push(tag)

      return [
        this.renderBaseTaskAction(record),
        reviewArr.filter(v =>(v.name !== 'temp')).map(review => {
          return <i18n path="common.record.task.taskReviewModifield" tag="div">
            <strong place="data1">{ review.name }</strong>
            <strong place="value1"><biz-comment-html html={ review.oldValue }></biz-comment-html></strong>
            <strong place="value2"><biz-comment-html html={ review.newValue }></biz-comment-html></strong>
          </i18n>
        })
      ]
    },
    /* 渲染工单服务报告dom */
    renderTaskServiceReportDom(record = {}) {
      let { userName, taskNo, attachments, content, staffId, userId } = record;
      let SRDOM = <i18n path="common.record.task.taskServiceReport.record1"  tag="span">
        <strong place="operator">{ this.renderUserName(userName, staffId, userId) }</strong>
        <span place="taskNo">{taskNo}</span>
      </i18n>
      let REJECTDOM = ''

      if(content && Object.keys(content).length > 0) {
        if(content.operation === 'send') {
          SRDOM = <i18n path="common.record.task.taskServiceReport.record2" tag="span">
          <strong place="operator">{ content.operator }</strong>
          <span place="recipient">{ content.recipient }</span>
        </i18n>
        } else if(content.operation === 'confirm') {
          SRDOM = <i18n path="common.record.task.taskServiceReport.record3" tag="span">
            <strong place="operator">{t('common.base.customer')}{ content.operator }</strong>
          </i18n>
        } else if(content.operation === 'refuse') {
          SRDOM = <i18n path="common.record.task.taskServiceReport.record4" tag="span">
              <strong place="operator">{t('common.base.customer')}{ content.operator }</strong>
            </i18n>
          REJECTDOM = <div class='mar-t-10'>{t('task.refuseReason')}：{ content.dissentContent }</div>
        } else if (content.operation === 'create') {
          SRDOM = <i18n path="common.record.task.taskServiceReport.record5" tag="span">
            <strong place="operator">{ this.renderUserName(userName, staffId, userId) }</strong>
            <span place="taskNo">{taskNo}</span>
          </i18n>
        }
      }
      return <div>{ SRDOM } {createAttachmentDom(h, attachments, 'serviceReport')} {REJECTDOM}</div>
    },
    /* 渲染工单超时dom */
    renderTaskTimeoutDom(record = {}) {
      let { content } = record;
      return [
        <i18n path="common.record.task.taskTimeOut" tag="div">
          <span place="operator">{ this.renderSynergyName(content.receivers, content.receiversStaffId) }</span>
        </i18n>,
        content.flow && <div>{t('task.record.processNode')}： { this.getActionLabel(content.flow) }</div>,
        <div>{t('task.record.processTimeout')}：{ formatDate(content.overTime) }</div>
      ]
    },
    /* 渲染工单已超时dom */
    renderTaskTimeoutdDom(record = {}) {
      let { content, taskNo } = record;
      return <div class="task-record-fail">{t('common.record.task.taskHadTimeOut', {taskNo, flow: this.getActionLabel(content.flow)})}</div>
    },
    /* 渲染工单转交dom */
    renderTaskTransferDom(record = {}) {
      let { executorName, userName, executorId, content, taskNo, staffId, executorStaffId, userId } = record;
      return [
        <i18n path="common.record.task.taskTransfer" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="taskNo">{taskNo}</span>
        </i18n>,
        executorId && <div>{t('task.record.modifyExecutorTo')}：{this.renderUserName(executorName, executorStaffId, executorId)}</div>,
        content.synergy && <div>{t('task.record.modifySynergiesTo')}：{ this.renderSynergyName(content.synergy, content.synergyStaffId) }</div>
      ]
    },
    /* 渲染工单审批转交dom */
    renderTaskApproveTransferDom(record = {}) {
      let { operatorName, handoverName, operatorStaffId, handoverStaffId, operatorId } = record?.content;
      return <i18n path="common.record.task.taskApproveTransfer" tag="h5">
          <strong place="operator">{this.renderUserName(operatorName, operatorStaffId, operatorId)}</strong>
          <strong place="approve">{ this.renderUserName(handoverName, handoverStaffId) }</strong>
        </i18n>
    },
    /* 渲染备件服务清单dom */
    renderSparepartAndServiceListDom(record = {}) {
      let { userName, content = {}, staffId, userId } = record;
      let { action, inventoryTypeName } = content;
      let partList = JSON.parse(content.partList || '[]');

      if (action == '出库申请') {
        return <i18n path={`common.record.task.sparepartAndServiceList['${action}']`} tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="inventoryTypeName">{inventoryTypeName}</span>
        </i18n>
      }

      return <i18n path={`common.record.task.sparepartAndServiceList['${action}']`} tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="inventoryTypeName">{inventoryTypeName}</span>
          <span place="ohter">{partList.join('，')}</span>
        </i18n>
    },
    // 与renderSparepartAndServiceListDom重复
    renderMaterialApply(record = {}) {
      let { userName, content = {}, staffId, userId } = record;
      let { action, inventoryTypeName } = content;
      let partList = JSON.parse(content.partList || '[]');

      if (action == '出库申请') {
        return <i18n path={`common.record.task.sparepartAndServiceList['${action}']`} tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="inventoryTypeName">{inventoryTypeName}</span>
        </i18n>
      }

      return <h5>{this.renderUserName(userName, staffId, userId)} 在附加组件【{ inventoryTypeName }】中{ action }了 { partList.join('，') }。</h5>
    },
    // 渲染呼叫中心呼叫动态
    renderCallCenterRecord(record = {}) {
      return (
        <biz-call-center-record record={record} />
      )
    },
    // 人脸识别日志
    renderFaceIdRecord(record = {}) {
      let { userName, content, staffId, userId, action, taskNo } = record;
      return <span>
        <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
        {action === 'FACE_AUTH_PASSED' ? t('common.record.task.faceIdIsPass') : t('common.record.task.faceIdIsNotPass')}
        #{taskNo}
      </span>
    },
    // 提交自定义节点
    renderSubmitNodeRecord(record = {}) {
      let { userName, content, staffId, userId, taskNo } = record;
      return (
          <div>
            <span>{this.renderUserName(userName, staffId, userId)}</span>
            { this.$t('common.record.task.submitCustomNode', {btnName: content && content.buttonName, taskNo}) }
          </div>
      )
    },
    // 添加自定义节点负责人
    renderInsertNodeExecutorRecord(record = {}) {
      let { userName, content, staffId, userId, taskNo } = record;
      let users = []
      try {
        users = JSON.parse(content.insertUserList)
      } catch (e) {return []}

      return (
          <div>
            <span>{this.renderUserName(userName, staffId, userId)}</span>
            <i18n path="common.record.task.insertCustomNodeUser" tag="span">
              <span place="users">
                { users.map((item, index)=> <span>{index!==0 && ','}{this.renderUserName(item.displayName, item.staffId, item.userId)}</span>) }
              </span>
              <span place="nodeName">{ content && content.nodeName }</span>
              <span place="taskNo">{ taskNo }</span>
            </i18n>
          </div>
      )
    },
    // 添加自定义节点负责人
    renderDeleteNodeExecutorRecord(record = {}) {
      let { userName, content, staffId, userId, taskNo } = record;
      let users = []
      try {
        users = JSON.parse(content.deleteUserList)
      } catch (e) {return []}

      return (
          <div>
            <span>{this.renderUserName(userName, staffId, userId)}</span>
            <i18n path="common.record.task.deleteCustomNodeUser" tag="span">
              <span place="users">
                { users.map((item, index)=> <span>{index!==0 && ','}{this.renderUserName(item.displayName, item.staffId, item.userId)}</span>) }
              </span>
              <span place="nodeName">{ content && content.nodeName }</span>
              <span place="taskNo">{ taskNo }</span>
            </i18n>
          </div>
      )
    },
    /** 根据记录的action渲染对应的内容，支持jsx和render函数 */
    renderRecord(h, record) {
      let { action, userName, content, attachments, taskNo, staffId, userId } = record;
      if (action == '指派' || action == '转派' || action === '指派回访') return this.renderAllotDom(record)
      if (action == '开始' || action == '完成') return this.renderStartOrFinishDom(record)
      if (action == '出发') return this.renderSetOutDom(record)
      if (action == '编辑回执') return this.renderReceiptEditDom(record)
      if (action == '添加') return this.renderActionRemarkDom(h, record)
      if (action == '留言') return this.renderLeaveMessageDom(h, record)
      if (action == '发布') return this.renderReleaseTaksPoolDom(record)
      if (action == '接受') return this.renderTaskAcceptDom(record)
      if (action == '新建') return this.renderTaskCreatetDom(record)
      if (action === 'API新建') return this.renderApiCreateDom(record)
      if (action === '计划任务新建') return this.renderPlanTaskCreateDom(record)
      if (action === '审批') return this.renderTaskApproveDom(record)
      if (action === '卡片') return this.renderTaskCardDom(record)
      if (action === '自动分配') return this.renderTaskAutoAllotDom(record)
      if (action === '自动分配失败') return this.renderTaskAutoAllotFailDom(record)
      if (action === '自动派单') return this.renderTaskAutoDispatchDom(record)
      if (action === '超时') return this.renderTaskTimeoutDom(record)
      if (action === '已超时') return this.renderTaskTimeoutdDom(record)
      if (action === '修改') return this.renderTaskEditDom(record)
      if (action === '转交') return this.renderTaskTransferDom(record)
      if (action === '暂停') return this.renderTaskPausedDom(record)
      if (action === '回访短信') return this.renderTaskCodeReviewDom(record)
      if (action === '回访' || action === '完成回访' || action === '回访并关闭' || action === '暂存') return this.renderTaskReviewDom(record)
      if (action === '修改结算') return this.renderTaskBalanceDom(record)
      if (action === '服务报告') return this.renderTaskServiceReportDom(record)
      if (action == '电话日志') return this.renderPhoneLogDom(record)
      if (action == '支付') return this.renderTaskPaymentDom(record)
      if (action == '审核转交') return this.renderTaskApproveTransferDom(record)
      if (action == '备件清单' || action == '服务清单' || action == '物料申领') return this.renderSparepartAndServiceListDom(record)
      if (action === '自定义异常') return this.abnormalRender(record)
      if (action === '附件') return this.renderAttachment(record)
      if (action === '编辑') return this.renderEditSettlement(record)
      if (action === '连接器to') return this.renderConnectorTo(record)
      if (action === '连接器from') return this.renderConnectorFrom(record)
      if (action === '触发器to') return this.renderTriggerTo(record)
      if (action === '触发器from') return this.renderTriggerFrom(record)
      if (action === '坐席呼出') return this.renderCallCenterRecord(record)
      if (action === 'FACE_AUTH_PASSED') return this.renderFaceIdRecord(record)
      if (action === 'FACE_AUTH_FAILED') return  this.renderFaceIdRecord(record)
      if (action === 'submitNode') return  this.renderSubmitNodeRecord(record)
      if (action === 'insertNodeExecutor') return  this.renderInsertNodeExecutorRecord(record)
      if (action === 'deleteNodeExecutor') return  this.renderDeleteNodeExecutorRecord(record)



      const { isGoBack, synergy, updateType, updateContent, customReason, customExceptionReason } = content;
      const reason = customExceptionReason || customReason;
      // 根据后端返回action做翻译枚举
      const actionDes = translateAction(action)

      return [
        // 刀马后端要求前端自己翻译action他负责提供action类别 有遗漏或者拓展问题找后端确认
        <i18n path="common.record.task.normal" tag="h5">
          <span place="operator">{this.renderUserName(userName, staffId, userId)}</span>
          <span place="action">{actionDes}</span>
          <span place="taskNo">{taskNo}</span>
        </i18n>,
        synergy && <div>{t('common.label.synergiesUser')}：{ this.renderSynergyName(synergy, content.synergyStaffId) }</div>,
        (updateType == 'tRecord' && reason) && <div>{`${actionDes}${t('common.base.reason')}：${reason}`}</div>,
        (updateType == 'tRecord' && updateContent) && <div>{t('common.base.detailsReason')}：<biz-comment-html html={updateContent}></biz-comment-html></div>,
        isGoBack !== undefined && <div> {isGoBack !== null ? isGoBack == '1' ? t('common.record.task.partBackUp.back') : t('common.record.task.partBackUp.notBack') : ''} </div>,
        createAttachmentDom(h, attachments)
      ];
    },
    renderUserName(userName, staffId, userId){
      return (
        <recordUserName userName={userName} staffId={staffId} userId={userId} />
      )
    },
    renderSynergyName(synergy, synergyStaffId){
      if(isOpenData && synergy != '自动审批' && synergyStaffId) {
        const sids = synergyStaffId.split(',') || []
        if(sids.length) return sids.map(item=><open-data key={item} type="userName" openid={item}></open-data>)
      }
      return synergy
    },
    async searchRecord() {
      try {
        this.recordLoading = true;

        let data = await this.fetchRecord(this.params);

        this.recordLoading = false;
        this.recordPage.list = [];
        this.recordPage.merge(data.result)

      } catch (error) {
        console.warn('searchRecord -> error', error)
      }
    },
    async getUserSetForNoteCustomerStorage(){
      try{
        if(storageGet(hideNoteStorageKey) === 1){
          this.hideTips = true
        }
        let store_ = await getUserGuideStorageBase()
        
        if(store_?.[checkNoteToCustomerStorageKey]?.isComplete === 1){
          this.alwaysCheckToCustomer = true
        }
      }catch(err){
        console.error(err)
      }
    },
    saveNoteToCustomer(e){
      let arr = []
      this.alwaysCheckToCustomer = e
      arr.push({
        type:checkNoteToCustomerStorageKey,
        isComplete:e ? 1 : 0,
        step:1
      })
      setUserGuideStorageBase({
        userGuideList: arr
      })
    },
    changeHideTips:debounce(function(e){
      storageSet(hideNoteStorageKey, e ? 1 : 0)
    }, 500)
  }
}
</script>
<style lang="scss">

.form-view-row-content-address{
  cursor: pointer;
}
div.form-view-row-content-address>span{
  display: block;
}
.form-view-row-content-address:hover{
    color:$color-primary-light-6
 }
.task-timeline{
  padding-top: 15px;
  flex: 1;
  padding-right: 15px;
  .private {
    @include fontColor();
  }
}
.task-position-exception,
.task-record-fail {
  color: #f0ad4e;
}

.task-info-record {
  height: 100%;
  display: flex;
  flex-flow: column nowrap;
  background-color: #fff;
}
.form-approve-signatures {
  display:grid;
  grid-template-columns: 35px 1fr;
}
</style>
<style lang="scss" scoped>
.serviceReport ::v-deep .base-file-info > .base-file-info-name {
  color: $color-primary-light-6;
}

</style>
